import { Vector3, Matrix3, BufferGeometry, BufferAttribute, LineSegments, LineBasicMaterial } from 'three'

const _v1 = new Vector3()
const _v2 = new Vector3()
const _normalMatrix = new Matrix3()

class CubeHelper extends LineSegments {
  constructor(object, color = 0xffff00) {
    const indices = new Uint16Array([0, 2, 2, 3, 3, 1, 1, 0, 5, 7, 7, 6, 6, 4, 4, 5, 0, 5, 2, 7, 3, 6, 1, 4])

    const positions = new Float32Array(8 * 3)
    const geometry = new BufferGeometry()
    geometry.setIndex(new BufferAttribute(indices, 1))
    geometry.setAttribute('position', new BufferAttribute(positions, 3))
    super(
      geometry,
      new LineBasicMaterial({
        color: color,
        toneMapped: false,
      })
    )
    this.object = object
    this.type = 'CubeHelper'
    this.matrixAutoUpdate = false
    this.update()
  }

  update(object) {
    this.computeVertexNormals()
    if (object !== undefined) {
      console.warn('CubeHelper: .update() has no longer arguments.')
    }

    this.geometry.computeBoundingSphere()
  }

  computeVertexNormals() {
    this.object.updateMatrixWorld(true)

    _normalMatrix.getNormalMatrix(this.object.matrixWorld)

    const matrixWorld = this.object.matrixWorld

    const position = this.geometry.attributes.position
    const array = position.array

    const objGeometry = this.object.geometry

    if (objGeometry && objGeometry.vertices) {
      const vertices = objGeometry.vertices
      /*
                  7____5
                2/___0/|
                | 6__|_4
                3/___1/
            */
      for (let j = 0, jl = vertices.length; j < jl; j++) {
        _v1.set(vertices[j].x, vertices[j].y, vertices[j].z).applyMatrix4(matrixWorld)
        array[j * 3] = _v1.x.toFixed(2)
        array[j * 3 + 1] = _v1.y.toFixed(2)
        array[j * 3 + 2] = _v1.z.toFixed(2)
      }
    } else if (objGeometry && objGeometry.isBufferGeometry) {
      const objPos = objGeometry.attributes.position

      const objNorm = objGeometry.attributes.normal

      let idx = 0

      // for simplicity, ignore index and drawcalls, and render every normal

      for (let j = 0, jl = objPos.count; j < jl; j++) {
        _v1.set(objPos.getX(j), objPos.getY(j), objPos.getZ(j)).applyMatrix4(matrixWorld)

        console.log(j, _v1, objPos.getX(j), objPos.getY(j), objPos.getZ(j))

        _v2.set(objNorm.getX(j), objNorm.getY(j), objNorm.getZ(j))

        _v2.applyMatrix3(_normalMatrix).normalize().multiplyScalar(this.size).add(_v1)

        position.setXYZ(idx, _v1.x, _v1.y, _v1.z)

        idx = idx + 1

        position.setXYZ(idx, _v2.x, _v2.y, _v2.z)

        idx = idx + 1
      }
    }

    position.needsUpdate = true
  }

  setFromObject(object) {
    this.object = object
    this.update()
    return this
  }

  copy(source) {
    LineSegments.prototype.copy.call(this, source)
    this.object = source.object
    return this
  }
}

export { CubeHelper }
